package tabuInterface.algorithm;

import tabuInterface.algorithm.tabuList.TabuList;
import tabuInterface.algorithm.tabuLogic.TabuLogic;
import tabuInterface.gene.Gene;
import tabuInterface.gene.GeneNoParameter;
import tabuInterface.gene.GetNeighborhoodFromNoParameter;

import java.util.EnumMap;

public abstract class TabuSearchNoParameter implements TabuSearch {
    private TabuList tabuList;//禁忌表
    public int iterNum;//一轮禁忌搜索的迭代次数
    public int tabuNum;//禁忌搜索的次数
    public TabuLogic pardon;//特赦条件

    public TabuList getTabuList() {
        return tabuList;
    }

    public void setTabuList(TabuList tabuList) {
        this.tabuList = tabuList;
    }

    public TabuSearchNoParameter(TabuList tabuList, int iterNum, int tabuNum, TabuLogic pardon) {
        this.tabuList = tabuList;
        this.iterNum = iterNum;
        this.tabuNum = tabuNum;
        this.pardon = pardon;
    }


    @Override
    public EnumMap<IterReturnMapKey, Object> run() throws Exception {
        int finalAns=Integer.MAX_VALUE;
        Gene finalGene = null;
        for(int i=0;i<tabuNum;i++){
            EnumMap<IterReturnMapKey, Object> tmap=runIter();
            int iterAns= (int)tmap.get(IterReturnMapKey.EVAL_VALUE);
            if(finalAns>iterAns){
                finalAns=iterAns;
                finalGene=(Gene) tmap.get(IterReturnMapKey.GENE);
            }

        }
        EnumMap<IterReturnMapKey, Object> finalReturn=new EnumMap<IterReturnMapKey, Object>(IterReturnMapKey.class) ;
        finalReturn.put(IterReturnMapKey.EVAL_VALUE,(Object) finalAns);
        finalReturn.put(IterReturnMapKey.GENE,(Object) finalGene);

        return finalReturn;


    }


    @Override
    public EnumMap<IterReturnMapKey, Object> runIter() throws Exception{
        Gene iterBestGene=iterInit();
        int iterBestValue=eval(iterBestGene);

        Gene pardonGene=null,curGene=null;//特赦解和非特赦解
        int  pardonValue=Integer.MAX_VALUE,curValue=Integer.MAX_VALUE;//
        //特赦解并不是一定会成为特赦解
        //实际操作中把被禁忌的最优基因存入，作为待特赦对象，
        //最终是否特赦并不在循环中判断

        //迭代
        for(int i=0;i<iterNum;i++){
            //邻域搜索
            //邻域的大小和优劣影响到搜索效果和速度
            Gene[] genes= ((GeneNoParameter)iterBestGene).neighborhood();
            if(genes==null)
                throw new Exception("don't  have genes neighborhood.please check Gene iterInit() ");
            for (Gene gene:genes) {
                int tmpValue=eval(gene);
                if(tabuList.isTabu(iterBestGene,gene)){//被禁忌
                    if(tmpValue<pardonValue){
                        pardonGene=gene;
                        pardonValue=tmpValue;
                    }

                }
                else{//没有被禁忌
                    if (tmpValue<curValue){
                        curGene=gene;
                        curValue=tmpValue;
                    }
                }


            }
            //邻域搜索结束
            //特赦开始
            if(pardon.exec()){//特赦
                curGene=pardonGene;
                curValue=pardonValue;
            }

            //尝试更新
            if(curValue<iterBestValue){

                //更新禁忌表
                tabuList.update(iterBestGene,curGene);

                iterBestValue=curValue;
                iterBestGene=curGene;
            }

        }
        EnumMap<IterReturnMapKey, Object> iterBest=new EnumMap<IterReturnMapKey, Object>(IterReturnMapKey.class);
        iterBest.put(IterReturnMapKey.GENE,iterBestGene);
        iterBest.put(IterReturnMapKey.EVAL_VALUE,iterBestValue);


        return iterBest;
    }


    @Override
    public abstract int eval(Gene gene) ;//评估基因

    @Override
    public abstract Gene iterInit() ;//初始基因生成

}

